class Animal{
    public String name;
    public int age;
//    private int age;  子类不能继承父类的私有变量（私有只能在自己的类中访问）

    /*public Animal(){
        //JVM会默认自动提供一个不带参数的构造方法，自动初始化
        //并且会在子类中有一个默认提供的super()与之对应。
    }*/
    //如果自己定义了一个构造方法，那么编译器将不会提供不带参数的构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Animal(String int)");
    }

    static {
        System.out.println("Animal::static{}");
    }

    {
        System.out.println("Animal::{}");
    }

    public void eat(){
        System.out.println(name + "在吃饭！");
    }
}
class Dog extends Animal{
    public boolean silly;   //自己的属性
    public String name = "糊糊";

    //子类构造方法
    public Dog(String name, int age, boolean silly){
        //如果子类有自己的构造方法，在子类完成自己的构造方法之前，必须先帮父类完成初始化
        super(name, age);   //先帮父类部分初始化--super必须放第一行
        this.silly = silly;
        System.out.println("Dog(String name, int age, boolean silly)");
    }

    static {
        System.out.println("Dog::static{}");
    }

    {
        System.out.println("Dog::{}");
    }

    public void houseGuard(){
        System.out.println(super.name + "在看家护院！");
    }
}
class Cat extends Animal{
    //如果父类有自己的构造方法，那么子类必须有一个自己的构造方法用来帮父类完成初始化
    public Cat(String name, int age) {
        super(name, age);
        System.out.println("Cat(String, int)");
    }

    static {
        System.out.println("Cat::static{}");
    }

    {
        System.out.println("Cat::{}");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog("柚子",2,false);
        System.out.println("===================");
        /*dog.name = "糊糊";
        dog.eat();
        dog.houseGuard();*/

        Cat cat = new Cat("胖朵",1);
    }
}

/*
* 如果父类和子类都有代码块，则运行顺序：
* 1.静态代码块（先父类、再子类）
* 2.父类普通代码块、父类构造方法
* 3.子类普通代码块、子类构造方法
* 注意：如果有多个子类，由于每个静态代码块只有一份，所以每个子类在调用父类时，
*      父类的静态代码块只会在第一个调用父类的子类中出现一次，其他子类输出结果不会再出现父类的静态代码块，只会出现自己的静态代码块。
* */